#!/usr/bin/python -S
"""
examples_test.py: Miscellaneous examples
"""

__author__ = 'Andy Chu'


import os
from pprint import pprint
import sys

from pan.core import cmdapp
from pan.core import params
from pan.core import json
from pan.core import util
from pan.test import testy

if __name__ == '__main__':
  # for jsonpattern package
  sys.path.insert(
      0, os.path.join(os.path.dirname(__file__), '..', 'python'))
  # Root of the project
  sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))

from tests import test_main

import jsonpattern


class ExamplesTest(testy.Test):

  LABELS = ['multilanguage']

  def testCompileTime(self):
    p = r"""
        P| \\
         | $value
        P|     {.chars abfnrtv ? " ' \ }
         | end
        """
    p = jsonpattern.Pattern(p)

  def testEscapedStringEval(self):
    library = {}

    filters = {
       # A little hack to save some typing
       'escape-char': lambda c: eval(r'"\%s"' % c)
       }

    def Add(name, pattern, desc=None):
      library[name] = jsonpattern.Pattern(
          pattern, patterns=library, filters=filters, name=name, desc=desc)

    # Based on this example from:
    # http://code.google.com/p/protobuf/source/browse/trunk/src/google/protobuf/io/tokenizer.cc
    #
    # Syntax matters!
    """
    kString  = new RE("(\"([^\"\\\\]|"              // non-escaped
                      "\\\\[abfnrtv?\"'\\\\0-7]|"   // normal escape
                      "\\\\x[0-9a-fA-F])*\"|"       // hex escape
                      "\'([^\'\\\\]|"        // Also support single-quotes.
                      "\\\\[abfnrtv?\"'\\\\0-7]|"
                      "\\\\x[0-9a-fA-F])*\')");
    """

    p = r"""
        P| \\
         | $value | escape-char
        P|     {.chars abfnrtv ? " ' \ }
         | end
        """
    Add('normal-escape', p)

    p = r"""
        P| \\
         | $value | oct2int | chr
        P|     {.chars 0-7}+
         | end
        """
    Add('octal-escape', p)

    self.verify.Match(library['octal-escape'], r'\011', '\011')

    p = r"""
        P| \\x
         | $value | hex2int | chr
        P|     {.chars 0-9 a-f A-F }+
         | end
        """
    Add('hex-escape', p)

    self.verify.Match(library['hex-escape'], r'\x11', '\x11')

    p = r"""
         | choice
        P|     {:hex-escape}
         | end
        """
    Add('sub-test', p)

    self.verify.Match(library['sub-test'], r'\x11', '\x11')

    p = r"""
        P| "
         | $repeated
         |   choice
         |     $value
        P|       {!chars " \ }+
         |     end
         |   or
        P|     {:normal-escape}
         |   or
        P|     {:octal-escape}
         |   or
        P|     {:hex-escape}
         |   end
         | end
        P| "
        """
    Add('double-quoted', p)

    p = r"""
        P| '
         | $repeated
         |   choice
         |     $value
        P|       {!chars ' \ }+
         |     end
         |   or
        P|     {:normal-escape}
         |   or
        P|     {:octal-escape}
         |   or
        P|     {:hex-escape}
         |   end
         | end
        P| '
        """
    Add('single-quoted', p)

    print library['single-quoted'].AsTree()

    p = r"""
         | choice
        P|   {:double-quoted}
         | or
        P|   {:single-quoted}
         | end
        """
    Add('literal', p)

    p = library['literal']

    print p.AsTree()

    self.verify.Match(p, r'"hello"', [r'hello'])
    self.verify.Match(p, r'"hello\n"', [r'hello', '\n'])
    self.verify.Match(p, r'"hello\r\n"', [r'hello', '\r', '\n'])
    self.verify.Match(p, r'"hello\x00\n"', [r'hello', '\x00', '\n'])
    self.verify.Match(p, r'"hello\40\n"', [r'hello', r' ', '\n'])

    self.verify.Match(p, r"'hello'", [r'hello'])
    self.verify.Match(p, r"'hello\n'", [r'hello', '\n'])
    self.verify.Match(p, r"'hello\r\n'", [r'hello', '\r', '\n'])
    self.verify.Match(p, r"'hello\x00\n'", [r'hello', '\x00', '\n'])
    self.verify.Match(p, r"'hello\40\n'", [r'hello', ' ', '\n'])

    p = r"""
         | choice | join-strings
        P|   {:double-quoted}
         | or
        P|   {:single-quoted}
         | end
        """

    Add('joined', p)
    p = library['joined']

    self.verify.Match(p, r"'hello'", 'hello')
    self.verify.Match(p, r"'hello\n'", 'hello\n')
    self.verify.Match(p, r"'hello\r\n'", 'hello\r\n')
    self.verify.Match(p, r"'hello\x00\n'", 'hello\x00\n')
    self.verify.Match(p, r"'hello\40\n'", 'hello \n')


if __name__ == '__main__':
  test_main.main(__import__(__name__), sys.argv[1:])
